package org.pwwong.scalautils.animation

import org.pwwong.scalautils.animation.Predef._

import org.pwwong.scalautils.signals.{BindableSignal,Signal}
import org.pwwong.scalautils.time._

object Animation {
  def apply[T](startEnd:(T,T))(implicit evaluator:(Double,T,T)=>T) = new StartEndAnimation[T](startEnd._1, startEnd._2)(evaluator)
}

abstract class Animation[T](implicit var evaluator:(Double,T,T)=>T) { self:Animation[T] =>
  var interpolator:(Double)=>Double = Interpolators.Linear
  var repeatBehavior:RepeatBehavior = NumberedRepeats(1,false)
  var framesPerSec:Int = 60
  var duration:Option[Duration] = None
  
  def in(dur:Duration):self.type = {duration = Some(dur); self}
  def at(fps:Int):self.type = {framesPerSec = fps; self}
  
  def repeat(numTimes:Int):self.type = {repeatBehavior = NumberedRepeats(numTimes,false); self}
  def cycle(numTimes:Int):self.type = {repeatBehavior = NumberedRepeats(numTimes,true); self}
  def repeatInfinite:self.type = {repeatBehavior = RepeatIndefinitely(false); self}
  def cycleInfinite:self.type = {repeatBehavior = RepeatIndefinitely(true); self}
    
  def withInterpolator(interp:(Double)=>Double):self.type = { interpolator = interp; self} 
  def withEvaluator(eval:(Double,T,T)=>T):self.type = { evaluator = eval; self}
}

// Carries the information necessary to build an AnimatedSignal
class StartEndAnimation[T](var startValue:T, var endValue:T)(implicit eval:(Double,T,T)=>T) extends Animation[T]()(eval){ self:StartEndAnimation[T] =>
  def to(start:T):self.type = {startValue=start; self}
  def from(end:T):self.type = {endValue=end; self}
}
class EndAnimation[T](val endValue:T)(implicit eval:(Double,T,T)=>T) extends Animation[T]()(eval);
class OffsetAnimation[T](val offsetValue:T)(implicit eval:(Double,T,T)=>T) extends Animation[T]()(eval);

